﻿using System;
using System.Collections.Generic;

namespace SystemWnioskujacy
{
    public class Rule
    {
        public string Name = String.Empty;
        public double grf = 1.0;
        public double irf = 1.0;
        public Queries RuleIf = new Queries();
        public Functions RuleThen = new Functions();
        public VariableDistance VD = new VariableDistance();

        public double n_grf = 1.0;
        public double n_irf = 1.0;

        public Rule() {
            
        }

        public Rule(Queries nQueries, Functions nFunctions)
        {
            RuleIf = nQueries;
            RuleThen = nFunctions;
        }

        public Rule(Queries nQueries, Functions nFunctions, double grf, double irf)
        {
            RuleIf = nQueries;
            RuleThen = nFunctions;
            this.grf = n_grf = grf;
            this.irf = irf;
        }

        private bool Exists(string[][] T, int x, string[] R, int b)
        {
            for (int i = 0; i < T[0].Length && i < b; i++)
            {
                for (int j = 0; j < x + 1; j++)
                {
                    if (T[j][i] != R[j]) break;
                    if (j == x) return true;
                }
            }

            return false;
        }

        private string[] GetRow(string[][] T, int x, int j)
        {
            string[] R = new string[x + 1];

            for (int i = 0; i < R.Length; i++) R[i] = T[i][j];

            return R;
        }

        public void Merge(ref string[][] R, string[][] nR, int x)
        {
            if (x == 0)
            {
                for (int i = 0; i < nR.Length; i++) R[i] = nR[i];
            }
            else
            {
                string[][] tR = new string[x + nR.Length][];
                for (int i = 0; i < tR.Length; i++) tR[i] = new string[0];

                for (int i = 0; i < R[x].Length; i++)
                {
                    for (int j = 0; j < nR[0].Length; j++)
                    {
                        string[] Row = GetRow(R, x, i);

                        if (R[x][i] == nR[0][j] && !Exists(R, x, Row, i))
                        {
                            Array.Resize(ref Row, Row.Length + nR.Length);
                            for (int a = 1; a < nR.Length; a++)
                            {
                                Row[x + a] = nR[a][j];
                            }

                            if (Exists(tR, tR.Length - 1, Row, tR[0].Length))
                            {
                                for (int a = 0; a < tR.Length; a++)
                                {
                                    Array.Resize(ref tR[a], tR[a].Length + 1);
                                    if (a <= x) tR[a][tR[a].Length - 1] = R[a][i];
                                    else tR[a][tR[a].Length - 1] = nR[1][j];
                                }
                                break;
                            }
                            for (int a = 0; a < tR.Length; a++)
                            {
                                Array.Resize(ref tR[a], tR[a].Length + 1);
                                if (a <= x) tR[a][tR[a].Length - 1] = R[a][i];
                                else tR[a][tR[a].Length - 1] = nR[1][j];
                            }
                        }
                    }
                }

                R = tR;
            }
        }

        public bool Check()
        {
            VD = new VariableDistance();
            for (int i = 0; i < RuleIf.Length; i++) VD.Add(RuleIf[i], i);

            for (int j = 0; j < 2; j++)
            {
                for (int i = 0; i < RuleIf.Length; i++)
                {
                    if (!Base.FactsBase.Execute(RuleIf[i])) return false;
                }
            }

            for (int i = 0; i < RuleThen.Length; i++) RuleThen[i]();

            return true;
        }

        public void Execute2()
        {
            for (int i = 0; i < RuleThen.Length; i++) RuleThen[i]();
        }

        public bool Check2()
        {
            VD = new VariableDistance();
            for (int i = 0; i < RuleIf.Length; i++) VD.Add(RuleIf[i], i);

            for (int j = 0; j < 2; j++)
            {
                for (int i = 0; i < RuleIf.Length; i++)
                {
                    if (!Base.FactsBase.Execute2(RuleIf[i], this)) return false;
                }
            }

            return true;
        }
    }
}
